rr library(Seurat) library(monocle)

Loading required package: Biobase
Loading required package: BiocGenerics
Loading required package: parallel

Attaching package: ‘BiocGenerics’

The following objects are masked from ‘package:parallel’:

    clusterApply, clusterApplyLB, clusterCall, clusterEvalQ,
    clusterExport, clusterMap, parApply, parCapply, parLapply,
    parLapplyLB, parRapply, parSapply, parSapplyLB

The following objects are masked from ‘package:Matrix’:

    colMeans, colSums, rowMeans, rowSums, which

The following objects are masked from ‘package:stats’:

    IQR, mad, sd, var, xtabs

The following objects are masked from ‘package:base’:

    anyDuplicated, append, as.data.frame, basename, cbind, colMeans,
    colnames, colSums, dirname, do.call, duplicated, eval, evalq,
    Filter, Find, get, grep, grepl, intersect, is.unsorted, lapply,
    lengths, Map, mapply, match, mget, order, paste, pmax, pmax.int,
    pmin, pmin.int, Position, rank, rbind, Reduce, rowMeans, rownames,
    rowSums, sapply, setdiff, sort, table, tapply, union, unique,
    unsplit, which, which.max, which.min

Welcome to Bioconductor

    Vignettes contain introductory material; view with
    'browseVignettes()'. To cite Bioconductor, see
    'citation(\Biobase\)', and for packages 'citation(\pkgname\)'.

Loading required package: VGAM
Loading required package: stats4
Loading required package: splines
Loading required package: DDRTree
Loading required package: irlba

rr library(dplyr)


Attaching package: ‘dplyr’

The following object is masked from ‘package:Biobase’:

    combine

The following objects are masked from ‘package:BiocGenerics’:

    combine, intersect, setdiff, union

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union

rr library(ggplot2) library(ggrepel) library(GOplot)

Loading required package: ggdendro
Loading required package: gridExtra

Attaching package: ‘gridExtra’

The following object is masked from ‘package:dplyr’:

    combine

The following object is masked from ‘package:Biobase’:

    combine

The following object is masked from ‘package:BiocGenerics’:

    combine

Loading required package: RColorBrewer

rr seurobj <- readRDS(‘../output/seurat_objects/180831/10x-180831’) cds <- readRDS(‘output/monocle/180831/10x-180831-monocle-monocle_genelist_T1T2T3_T4T5_res.1.5’)

cannot open compressed file 'output/monocle/180831/10x-180831-monocle-monocle_genelist_T1T2T3_T4T5_res.1.5', probable reason 'No such file or directory'Error in gzfile(file, \rb\) : cannot open the connection

Figure 1

rr

save_plot(\../figures/figures_paper/main_figures/figure1/10x-180831_tsne_depots.pdf\, p1, base_width=6, base_height=4.5)
save_plot(\../figures/figures_paper/main_figures/figure1/10x-180831_tsne_timepoints.pdf\, p2, base_width=4, base_height=3)
save_plot(\../figures/figures_paper/main_figures/figure1/10x-180831_tsne_t1_aligned.pdf\, p3, base_width=6, base_height=4.5)

Figure 2

Figure 3

Heatmap

Heatmap

rr

load('../output/monocle/180831/heatmaps')
heatmap <- heatmaps$heatmap_logFC0.3_ncluster6_filtered_genes
gridExtra::grid.arrange(heatmap$ph_res$gtable)

rr

save_plot(\../figures/figures_paper/main_figures/figure3/BEAM_heatmap_logFC0.3_ncluster6_filtered_genes.pdf\, heatmap$ph_res$gtable, base_width=7, base_height=8)

Pseudotime plots

Pseudotime plots

rr

#new_cds <- buildBranchCellDataSet(cds, progenitor_method='duplicate', branch_states=c(2,3), branch_point=1, branch_labels=c('Metabolic', 'ECM'), stretch=T)
#saveRDS(new_cds, file='../output/monocle/180831/10x-180831-monocle-monocle_genelist_T1T2T3_T4T5_res.1.5_duplicated-progenitor_stretched-pseudotime')
#new_cds <- readRDS('../output/monocle/180831/10x-180831-monocle-monocle_genelist_T1T2T3_T4T5_res.1.5_duplicated-progenitor_stretched-pseudotime')
#new cds contains duplicated progenitor cells (one assigned to each branch) and stretched Pseudotime
df_pdata <- pData(new_cds)[c('original_cell_id', 'Branch', 'State.labels', 'Pseudotime')]
Error in pData(new_cds) : object 'new_cds' not found

rr

width=6
height=5
save_plot(\../figures/figures_paper/main_figures/figure3/pseudotime_ADIPOQ.pdf\, adipoq_pt, base_width=width, base_height=height)
save_plot(\../figures/figures_paper/main_figures/figure3/pseudotime_UCP2.pdf\, ucp2_pt, base_width=width, base_height=height)
save_plot(\../figures/figures_paper/main_figures/figure3/pseudotime_DCN.pdf\, dcn_pt, base_width=width, base_height=height)
save_plot(\../figures/figures_paper/main_figures/figure3/pseudotime_APOD.pdf\, apod_pt, base_width=width, base_height=height)

Featureplots

rr genes <- c(‘ADIPOQ’, ‘UCP2’, ‘DCN’, ‘APOD’) featureplots_noleg <- FeaturePlot(seurobj, features.plot=genes, cols.use=c(‘gray’, ‘blue’), no.legend=T, do.return=T, no.axes=T, pt.size=1, max.cutoff=c(5))

rr featureplots_leg <- FeaturePlot(seurobj, features.plot=genes, cols.use=c(‘gray’, ‘blue’), no.legend=F, do.return=T, no.axes=T, pt.size=1, max.cutoff=c(5))

rr adipoq_fp <- featureplots_noleg\(ADIPOQ + theme(plot.title=element_blank()) ucp2_fp <- featureplots\)UCP2 + scale_color_gradient(name=‘Expression’, low=‘gray’, high=‘blue’, guide=‘colorbar’, limits=c(0,5)) + theme(plot.title=element_blank(), legend.title=element_text(size=20), legend.text=element_text(size=20), legend.key.height = unit(1.3, ‘cm’))

rr save_plot(../figures/figures_paper/main_figures/Figure3_beam/featureplots_metabolic.pdf, metabolic_fp, base_width=width, base_height=height)

Error in save_plot(\../figures/figures_paper/main_figures/Figure3_beam/featureplots_metabolic.pdf\,  : 
  object 'height' not found

GO bubble plot

rr name <- ‘heatmap_logFC0.3_ncluster6’ folder <- paste(‘../tables/tables_paper/all_tables/BEAM/’, name, sep=‘’) #clusters <- c(1,2,3,4,6) clusters <- c(2,6,3) gsea <- list() genelist <- list() for (i in clusters){ gsea_cluster <- read.table(paste(folder,’/REVIGO_cleaned/‘, ’REVIGO_cluster’, i, ’_cleaned.tsv’, sep=‘’), header=T) gsea_cluster[’cluster’] <- i genes_cluster <- read.table(paste(folder,’/genelist_cluster’, i, ‘.tsv’, sep=’’), header=T) gsea[[i]] <- gsea_cluster genelist[[i]] <- genes_cluster } gsea <- do.call(, gsea) genelist <- do.call(, genelist) create_terms <- function(gsea){ return(data.frame(category=gsea\(gsea.domain, ID=gsea\)revigo.term_ID, term=gsea\(revigo.description, adj_pval=gsea\)gsea.p.value, genes=gsea\(gsea.intersection, cluster=gsea\)cluster)) } create_genes <- function(genelist){ return(data.frame(ID=genelist\(gene_short_name, logFC=genelist\)avgLogFC_State2_State3)) } terms <- create_terms(gsea) genes <- create_genes(genelist) circ <- circle_dat(terms, genes)

rr

save_plot('../figures/figures_paper/main_figures/Figure3_beam/180831_beamGO_all-terms.pd_labels3_zscore4.5.pdf', p, base_width=20, base_height=7)

Percent.mito

rr

percent_mito_fp <- FeaturePlot(seurobj, features.plot=c('percent.mito.100'), cols.use=c('gray', 'blue'), no.legend=F, do.return=T, no.axes=T, max.cutoff = c(10))$percent.mito + ggtitle('') + scale_color_gradient(name='% mitochondrial\ngene expression', low='gray', high='blue', guide='colorbar') + theme(legend.key.height = unit(1.6, 'cm'))

rr

save_plot(\../figures/figures_paper/main_figures/figure3/featureplot_PERCENT_MITO.pdf\, percent_mito_fp, base_width=width, base_height=height)

BATLAS

rr

batlas_results <- read.table('../tables/tables_paper/supplementary_tables/BATLAS/BATLAS_branch_high_res.txt', sep='\t', header=T)
batlas_results['pseudotime_decile'] <- seurobj@meta.data$pseudotime_decile[match(batlas_results$sample, seurobj@meta.data$branch_high_res)]
batlas_results['branch'] <- seurobj@meta.data$branch[match(batlas_results$sample, seurobj@meta.data$branch_high_res)]
batlas_results <- batlas_results %>% mutate(block_branch = if_else(branch == 'Progenitor', 'Beginning', 'End'))
batlas_results['brown_centered'] <- batlas_results$brown - 0.5
batlas_results['ratio'] <- batlas_results$brown/batlas_results$white

rr

p <- ggplot(batlas_results, aes(x=as.factor(pseudotime_decile), y=brown_centered, fill=branch)) +
  geom_col(position = position_dodge2(width=0.9, preserve='single')) +
  labs(x=\Pseudotime\, fill=\Branch\, y=NULL) +
  scale_fill_manual(values=colormap.branches, labels=c('L', 'U', 'P')) +
  facet_grid(cols=vars(block_branch), switch='x') + 
  scale_y_continuous(limits=c(-0.5, 0.5), breaks=seq(-0.5, 0.5, by=0.5), labels=c('100% white', '50/50', '100% brown')) +
  theme(strip.background=element_blank(), axis.text.x=element_blank(), strip.placement='outside')
p

rr

save_plot('../figures/figures_paper/main_figures/figure3/BATLAS_results.pdf', p, base_height=5, base_width=8)

SOM Figures

Clusters

TF analysis

rr

fig <- plot_grid(
  TSNEPlot(seurobj, group.by='res.0.5', pt.size=pt.size.tsne, do.label=T),
  TSNEPlot(seurobj, group.by='res.0.7', pt.size=pt.size.tsne, do.label=T),
  TSNEPlot(seurobj, group.by='res.1', pt.size=pt.size.tsne, do.label=T),
  TSNEPlot(seurobj, group.by='res.1.5', pt.size=pt.size.tsne, do.label=T),
  ncol=2, labels='auto'
)

Metabolic and ECM genes

rr

FeaturePlot(seurobj, features.plot='Pseudotime')
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKCmBgYHtyfQpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShtb25vY2xlKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2dyZXBlbCkKbGlicmFyeShHT3Bsb3QpCmBgYAoKYGBge3J9CnNldXJvYmogPC0gcmVhZFJEUygnLi4vb3V0cHV0L3NldXJhdF9vYmplY3RzLzE4MDgzMS8xMHgtMTgwODMxJykKY2RzIDwtIHJlYWRSRFMoJy4uL291dHB1dC9tb25vY2xlLzE4MDgzMS8xMHgtMTgwODMxLW1vbm9jbGUtbW9ub2NsZV9nZW5lbGlzdF9UMVQyVDNfVDRUNV9yZXMuMS41JykKdDFfYWxpZ25lZCA8LSByZWFkUkRTKCcuLi9vdXRwdXQvc2V1cmF0X29iamVjdHMvMTgwNTA0LzEweC0xODA1MDQtY2NyZWdvdXQtYWxpZ25lZCcpCnNvdXJjZSgnLi4vY29kZS9jb2xvcnMuUicpCmBgYAoKI0ZpZ3VyZSAxCgpgYGB7ciBlY2hvPVQsIHJlc3VsdHM9J2hpZGUnLCBpbmNsdWRlPUZ9CnAxIDwtIFRTTkVQbG90KHNldXJvYmosIGdyb3VwLmJ5PSdkZXBvdCcsIGNvbG9ycy51c2U9Y29sb3JzLmRlcG90cywgcHQuc2l6ZT0wLjEsIG5vLmF4ZXM9VCkKCnAyIDwtIFRTTkVQbG90KHNldXJvYmosIGdyb3VwLmJ5PSd0aW1lcG9pbnQnLCBjb2xvcnMudXNlPWNvbG9ycy50aW1lcG9pbnRzLCBwdC5zaXplPTAuNSwgbm8uYXhlcz1GLCBkby5yZXR1cm49VCkgKyB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIHBsb3QubWFyZ2luPWdyaWQ6OnVuaXQoYygwLDAsMCwwKSwgIm1tIikpCgp0MV9hbGlnbmVkIDwtIFNldEFsbElkZW50KHQxX2FsaWduZWQsIGlkPSdkZXBvdCcpCnQxX2FsaWduZWRAaWRlbnQgPC0gZmFjdG9yKHQxX2FsaWduZWRAaWRlbnQsIGxldmVscz1jKCdTdXByYScsICdTdWJxJywgJ1BlcmknLCAnVmlzY2UnKSkKCnAzIDwtIFRTTkVQbG90KHQxX2FsaWduZWQsIGdyb3VwLmJ5PSdkZXBvdCcsIGNvbG9ycy51c2U9Y29sb3JzLmRlcG90cywgZG8ucmV0dXJuPVQsIHB0LnNpemU9MC41LCBuby5heGVzPVQpCgpwMyRkYXRhIDwtIHAzJGRhdGEgJT4lIG11dGF0ZShpZGVudD1mYWN0b3IoaWRlbnQsIGxldmVscz1jKCdWaXNjZScsICdTdXByYScsICdTdWJxJywgJ1BlcmknKSkpICU+JSBhcnJhbmdlCgpmaWcxIDwtIHBsb3RfZ3JpZChwMSwgcDIsIHAzLCBuY29sPTIpCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTIsIGZpZy5hbGlnbiA9ICJjZW50ZXIifQpmaWcxCmBgYAoKYGBge3J9CnNhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9GaWd1cmUxX292ZXJ2aWV3LzEweC0xODA4MzFfdHNuZV9kZXBvdHMucGRmIiwgcDEsIGJhc2Vfd2lkdGg9NiwgYmFzZV9oZWlnaHQ9NC41KQpzYXZlX3Bsb3QoIi4uL2ZpZ3VyZXMvZmlndXJlc19wYXBlci9tYWluX2ZpZ3VyZXMvRmlndXJlMV9vdmVydmlldy8xMHgtMTgwODMxX3RzbmVfdGltZXBvaW50cy5wZGYiLCBwMiwgYmFzZV93aWR0aD00LCBiYXNlX2hlaWdodD0zKQpzYXZlX3Bsb3QoIi4uL2ZpZ3VyZXMvZmlndXJlc19wYXBlci9tYWluX2ZpZ3VyZXMvRmlndXJlMV9vdmVydmlldy8xMHgtMTgwODMxX3RzbmVfdDFfYWxpZ25lZC5wZGYiLCBwMywgYmFzZV93aWR0aD02LCBiYXNlX2hlaWdodD00LjUpCmBgYAoKCiNGaWd1cmUgMgoKCmBgYHtyIGVjaG89VCwgcmVzdWx0cz0naGlkZScsIGluY2x1ZGU9Rn0KIzEweC0xODA4MzFfdHNuZV9kZXBvdHMKIzEweC0xODA4MzFfdHNuZV90aW1lcG9pbnRzCiMxMHgtMTgwODMxX3RyYWplY3RvcnlfZGVwb3RzCiMxMHgtMTgwODMxX3RyYWplY3RvcnlfdGltZXBvaW50cwojMTB4LTE4MDgzMV90c25lX3N0YXRlCgp0cmFqX1QgPC0gcGxvdF9jZWxsX3RyYWplY3RvcnkoY2RzLCBjb2xvcl9ieSA9ICJ0aW1lcG9pbnQiKSArIGdlb21fcG9pbnQoY29sb3I9J3doaXRlJywgc2l6ZT01KSArIGdlb21fcG9pbnQoYWVzKGNvbG91cj10aW1lcG9pbnQpLCBhbHBoYT0wLjEpICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jb2xvcnMudGltZXBvaW50cykgKyB0aGVtZShsZWdlbmQucG9zaXRpb249J2JvdHRvbScpCgp0c25lX2JyYW5jaGVzIDwtIFRTTkVQbG90KHNldXJvYmosIGdyb3VwLmJ5PSdTdGF0ZS5sYWJlbHMnLCBjb2xvcnMudXNlPWNvbG9ycy5zdGF0ZXMubGFiZWxzLCBuby5heGVzPVQsIHB0LnNpemU9cHQuc2l6ZS50c25lKSArIHRoZW1lKGxlZ2VuZC5qdXN0aWZpY2F0aW9uPSd0b3AnKQoKdHJhal9wdCA8LSBwbG90X2NlbGxfdHJhamVjdG9yeShjZHMsIGNvbG9yX2J5PSdQc2V1ZG90aW1lX3N0cmV0Y2hlZCcsIHNob3dfYnJhbmNoX3BvaW50cyA9IEYsIHNob3dfYmFja2JvbmU9RikgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnQobG93PScjOTBkOGYyJywgaGlnaD0nIzAwNjQ4OCcsIG5hbWU9J1BzZXVkb3RpbWVcbihzdHJldGNoZWQpJywgYnJlYWtzPWMoMCwgNTAsIDEwMCkpICsgdGhlbWVfdm9pZCgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ3JpZ2h0JywgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTYpLCBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTYpLCBsZWdlbmQua2V5LnNpemU9dW5pdCgwLjYsICdjbScpKQoKZnBfcHQgPC0gRmVhdHVyZVBsb3Qoc2V1cm9iaiwgZmVhdHVyZXMucGxvdD0nUHNldWRvdGltZV9zdHJldGNoZWQnLCBjb2xzLnVzZT1jKCcjOTBkOGYyJywgJyMwMDcxOWEnKSwgZG8ucmV0dXJuPVQsIG5vLmF4ZXM9VCwgcHQuc2l6ZT0xLCBuby5sZWdlbmQ9RikkUHNldWRvdGltZV9zdHJldGNoZWQgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnQobG93PScjOTBkOGYyJywgaGlnaD0nIzAwNjQ4OCcsIG5hbWU9J1BzZXVkb3RpbWVcbihzdHJldGNoZWQpJykgKyB0aGVtZShwbG90LnRpdGxlPWVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTIwKSwgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MjApLCBsZWdlbmQua2V5LmhlaWdodD11bml0KDEuMywgJ2NtJykpCgp0c25lX2RlcG90IDwtIFRTTkVQbG90KHNldXJvYmosIGdyb3VwLmJ5PSdkZXBvdCcsIGNvbG9ycy51c2U9Y29sb3JzLmRlcG90cywgcHQuc2l6ZT1wdC5zaXplLnRzbmUsIG5vLmF4ZXM9RikgKyB0aGVtZShsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMyksIGxlZ2VuZC5rZXkuaGVpZ2h0PXVuaXQoMC43LCAnY20nKSwgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCBwbG90Lm1hcmdpbj1ncmlkOjp1bml0KGMoMCwwLDAsMCksICJtbSIpKQoKZmlnMiA8LSBwbG90X2dyaWQoCiAgdHJhal9ULCB0c25lX2JyYW5jaGVzLCB0cmFqX3B0LCBmcF9wdCwgdHNuZV9kZXBvdCwgbmNvbD0yCikKYGBgCgpgYGB7ciwgZmlnLmhlaWdodCA9IDE1LCBmaWcud2lkdGggPSAxMiwgZmlnLmFsaWduID0gImNlbnRlciJ9CmZpZzIKYGBgCgoKYGBge3IgZWNobz1ULCByZXN1bHRzPSdoaWRlJywgaW5jbHVkZT1GfQojdHJhal9ULCB0c25lX2JyYW5jaGVzLCB0cmFqX3B0LCBmcF9wdCwgdHNuZV9kZXBvdCwgbmNvbD0yCnNhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9GaWd1cmUyX21vbm9jbGUvMTB4LTE4MDgzMV90cmFqZWN0b3J5X3RpbWVwb2ludHMucGRmIiwgdHJhal9ULCBiYXNlX3dpZHRoPTYsIGJhc2VfaGVpZ2h0PTQuNSkKCnNhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9GaWd1cmUyX21vbm9jbGUvMTB4LTE4MDgzMV90c25lX2JyYW5jaC5wZGYiLCB0c25lX2JyYW5jaGVzLCBiYXNlX3dpZHRoPTUsIGJhc2VfaGVpZ2h0PTQuNSkKCnNhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9GaWd1cmUyX21vbm9jbGUvMTB4LTE4MDgzMV90cmFqZWN0b3J5X3BzZXVkb3RpbWUucGRmIiwgdHJhal9wdCwgYmFzZV93aWR0aD01LCBiYXNlX2hlaWdodD0yKQoKc2F2ZV9wbG90KCIuLi9maWd1cmVzL2ZpZ3VyZXNfcGFwZXIvbWFpbl9maWd1cmVzL0ZpZ3VyZTJfbW9ub2NsZS8xMHgtMTgwODMxX3RzbmVfcHNldWRvdGltZS5wZGYiLCBmcF9wdCwgYmFzZV93aWR0aD01LjIsIGJhc2VfaGVpZ2h0PTMuNSkKCnNhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9GaWd1cmUyX21vbm9jbGUvMTB4LTE4MDgzMV90c25lX2RlcG90LnBkZiIsIHRzbmVfZGVwb3QsIGJhc2Vfd2lkdGg9My4zLCBiYXNlX2hlaWdodD0yLjI1KQpgYGAKCgojRmlndXJlIDMKCiMjSGVhdG1hcAoKSGVhdG1hcAoKYGBge3IsIGZpZy5oZWlnaHQgPSA3LCBmaWcud2lkdGggPSA2LCBmaWcuYWxpZ24gPSAiY2VudGVyIn0KbG9hZCgnLi4vb3V0cHV0L21vbm9jbGUvMTgwODMxL2hlYXRtYXBzJykKaGVhdG1hcCA8LSBoZWF0bWFwcyRoZWF0bWFwX2xvZ0ZDMC4zX25jbHVzdGVyNl9maWx0ZXJlZF9nZW5lcwpncmlkRXh0cmE6OmdyaWQuYXJyYW5nZShoZWF0bWFwJHBoX3JlcyRndGFibGUpCmBgYAoKYGBge3J9CnNhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9maWd1cmUzL0JFQU1faGVhdG1hcF9sb2dGQzAuM19uY2x1c3RlcjZfZmlsdGVyZWRfZ2VuZXMucGRmIiwgaGVhdG1hcCRwaF9yZXMkZ3RhYmxlLCBiYXNlX3dpZHRoPTcsIGJhc2VfaGVpZ2h0PTgpCmBgYAoKIyNQc2V1ZG90aW1lIHBsb3RzCgpQc2V1ZG90aW1lIHBsb3RzCgpgYGB7cn0KI25ld19jZHMgPC0gYnVpbGRCcmFuY2hDZWxsRGF0YVNldChjZHMsIHByb2dlbml0b3JfbWV0aG9kPSdkdXBsaWNhdGUnLCBicmFuY2hfc3RhdGVzPWMoMiwzKSwgYnJhbmNoX3BvaW50PTEsIGJyYW5jaF9sYWJlbHM9YygnTWV0YWJvbGljJywgJ0VDTScpLCBzdHJldGNoPVQpCiNzYXZlUkRTKG5ld19jZHMsIGZpbGU9Jy4uL291dHB1dC9tb25vY2xlLzE4MDgzMS8xMHgtMTgwODMxLW1vbm9jbGUtbW9ub2NsZV9nZW5lbGlzdF9UMVQyVDNfVDRUNV9yZXMuMS41X2R1cGxpY2F0ZWQtcHJvZ2VuaXRvcl9zdHJldGNoZWQtcHNldWRvdGltZScpCgpuZXdfY2RzIDwtIHJlYWRSRFMoJy4uL291dHB1dC9tb25vY2xlLzE4MDgzMS8xMHgtMTgwODMxLW1vbm9jbGUtbW9ub2NsZV9nZW5lbGlzdF9UMVQyVDNfVDRUNV9yZXMuMS41X2R1cGxpY2F0ZWQtcHJvZ2VuaXRvcl9zdHJldGNoZWQtcHNldWRvdGltZScpCiNuZXcgY2RzIGNvbnRhaW5zIGR1cGxpY2F0ZWQgcHJvZ2VuaXRvciBjZWxscyAob25lIGFzc2lnbmVkIHRvIGVhY2ggYnJhbmNoKSBhbmQgc3RyZXRjaGVkIFBzZXVkb3RpbWUKCmRmX3BkYXRhIDwtIHBEYXRhKG5ld19jZHMpW2MoJ29yaWdpbmFsX2NlbGxfaWQnLCAnQnJhbmNoJywgJ1N0YXRlLmxhYmVscycsICdQc2V1ZG90aW1lJyldCgojZ2V0IGV4cHJlc3Npb24gdmFsdWVzIGZvciBldmVyeSBjZWxsIElEIGZyb20gdGhlIG5ldyBjZHMKZ2VuZXMgPC0gYXMubWF0cml4KHQoc2V1cm9iakBkYXRhW2MoJ0FESVBPUScsICdNR1AnLCAnVUNQMicsICdEQ04nLCAnQVBPRCcpLCBkZl9wZGF0YSRvcmlnaW5hbF9jZWxsX2lkXSkpCgojY2JpbmQgdGhlIGV4cHJlc3Npb24gdmFsdWVzIHdpdGggdGhlIHJlbGV2YW50IG1ldGFkYXRhCmRmIDwtIGNiaW5kKGRmX3BkYXRhLCBhcy5kYXRhLmZyYW1lKGdlbmVzKSkKYGBgCgoKYGBge3IsIGZpZy5oZWlnaHQgPSA4LCBmaWcud2lkdGggPSAxMCwgZmlnLmFsaWduID0gImNlbnRlciJ9CnBsb3RfcHNldWRvdGltZSA8LSBmdW5jdGlvbihnZW5lLCBsZWdlbmQpewogIHAgPC0gZ2dwbG90KGRmLCBhZXNfc3RyaW5nKHg9J1BzZXVkb3RpbWUnLCB5PWdlbmUpKSArCiAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIGNvbG91ciA9ICJibGFjayIsIHNpemUgPSAxLCBzdHJva2UgPSAwLCBhbHBoYT0wLjIsIGFlcyhmaWxsPVN0YXRlLmxhYmVscyksIHNob3cubGVnZW5kPUYpCiAgCiAgaWYgKGxlZ2VuZCl7CiAgICBwIDwtIHAgKyBnZW9tX3Ntb290aChzZSA9IEZBTFNFLCBhZXMoY29sb3I9QnJhbmNoKSwgc3Bhbj0wLjksIG1ldGhvZD0nbG9lc3MnLCBzaXplPTIpCiAgfSBlbHNlIHsKICAgIHAgPC0gcCArIGdlb21fc21vb3RoKHNlID0gRkFMU0UsIGFlcyhjb2xvcj1CcmFuY2gpLCBzcGFuPTAuOSwgbWV0aG9kPSdsb2VzcycsIHNpemU9Miwgc2hvdy5sZWdlbmQ9RikKICB9CiAgcCA8LSBwICsgCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWNvbG9ycy5wc2V1ZG90aW1lLmxpbmVzKSArCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9Y29sb3JzLnBzZXVkb3RpbWUucG9pbnRzKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobWlub3JfYnJlYWtzPTEpICsKICAgIHhsYWIoJ1BzZXVkb3RpbWUgKHN0cmV0Y2hlZCknKSArCiAgICBnZ3RpdGxlKGdlbmUpICsKICAgIHlsYWIoJ0V4cHJlc3Npb24nKSArCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MzApLCBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0zMCksIGF4aXMudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xNSksIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MjApLCBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MzApLCBsZWdlbmQua2V5LnNpemU9dW5pdCgxLjUsICdjbScpKQogIHJldHVybihwKQp9CgphZGlwb3FfcHQgPC0gcGxvdF9wc2V1ZG90aW1lKCdBRElQT1EnLCBsZWdlbmQ9RikKdWNwMl9wdCA8LSBwbG90X3BzZXVkb3RpbWUoJ1VDUDInLCBsZWdlbmQ9VCkKZGNuX3B0IDwtIHBsb3RfcHNldWRvdGltZSgnRENOJywgbGVnZW5kPUYpCmFwb2RfcHQgPC0gcGxvdF9wc2V1ZG90aW1lKCdBUE9EJywgbGVnZW5kPVQpCgptZXRhYm9saWNfcHQgPC0gcGxvdF9ncmlkKGFkaXBvcV9wdCwgdWNwMl9wdCwgbmNvbD0yLCByZWxfd2lkdGhzPWMoMC40MTUsIDAuNTg1KSkKZWNtX3B0IDwtIHBsb3RfZ3JpZChkY25fcHQsIGFwb2RfcHQsIG5jb2w9MiwgcmVsX3dpZHRocz1jKDAuNDE1LCAwLjU4NSkpCgpwbG90X2dyaWQobWV0YWJvbGljX3B0LCBlY21fcHQsIG5jb2w9MSkKYGBgCgpgYGB7cn0Kd2lkdGg9MTIKaGVpZ2h0PTUKCnNhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9GaWd1cmUzX2JlYW0vcHNldWRvdGltZV9tZXRhYm9saWMucGRmIiwgbWV0YWJvbGljX3B0LCBiYXNlX3dpZHRoPXdpZHRoLCBiYXNlX2hlaWdodD1oZWlnaHQpCnNhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9GaWd1cmUzX2JlYW0vcHNldWRvdGltZV9lY20ucGRmIiwgZWNtX3B0LCBiYXNlX3dpZHRoPXdpZHRoLCBiYXNlX2hlaWdodD1oZWlnaHQpCgoKI3NhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9maWd1cmUzL3BzZXVkb3RpbWVfQURJUE9RLnBkZiIsIGFkaXBvcV9wdCwgYmFzZV93aWR0aD13aWR0aCwgYmFzZV9oZWlnaHQ9aGVpZ2h0KQojc2F2ZV9wbG90KCIuLi9maWd1cmVzL2ZpZ3VyZXNfcGFwZXIvbWFpbl9maWd1cmVzL2ZpZ3VyZTMvcHNldWRvdGltZV9VQ1AyLnBkZiIsIHVjcDJfcHQsIGJhc2Vfd2lkdGg9d2lkdGgsIGJhc2VfaGVpZ2h0PWhlaWdodCkKI3NhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9maWd1cmUzL3BzZXVkb3RpbWVfRENOLnBkZiIsIGRjbl9wdCwgYmFzZV93aWR0aD13aWR0aCwgYmFzZV9oZWlnaHQ9aGVpZ2h0KQojc2F2ZV9wbG90KCIuLi9maWd1cmVzL2ZpZ3VyZXNfcGFwZXIvbWFpbl9maWd1cmVzL2ZpZ3VyZTMvcHNldWRvdGltZV9BUE9ELnBkZiIsIGFwb2RfcHQsIGJhc2Vfd2lkdGg9d2lkdGgsIGJhc2VfaGVpZ2h0PWhlaWdodCkKYGBgCgojI0ZlYXR1cmVwbG90cwoKYGBge3IgZWNobz1ULCByZXN1bHRzPSdoaWRlJ30KZ2VuZXMgPC0gYygnQURJUE9RJywgJ1VDUDInLCAnRENOJywgJ0FQT0QnKQpmZWF0dXJlcGxvdHNfbm9sZWcgPC0gRmVhdHVyZVBsb3Qoc2V1cm9iaiwgZmVhdHVyZXMucGxvdD1nZW5lcywgY29scy51c2U9YygnZ3JheScsICdibHVlJyksIG5vLmxlZ2VuZD1ULCBkby5yZXR1cm49VCwgbm8uYXhlcz1ULCBwdC5zaXplPTEsIG1heC5jdXRvZmY9Yyg1KSkgCmZlYXR1cmVwbG90c19sZWcgPC0gRmVhdHVyZVBsb3Qoc2V1cm9iaiwgZmVhdHVyZXMucGxvdD1nZW5lcywgY29scy51c2U9YygnZ3JheScsICdibHVlJyksIG5vLmxlZ2VuZD1GLCBkby5yZXR1cm49VCwgbm8uYXhlcz1ULCBwdC5zaXplPTEsIG1heC5jdXRvZmY9Yyg1KSkgCgphZGlwb3FfZnAgPC0gZmVhdHVyZXBsb3RzX25vbGVnJEFESVBPUSArIHRoZW1lKHBsb3QudGl0bGU9ZWxlbWVudF9ibGFuaygpKQoKdWNwMl9mcCA8LSBmZWF0dXJlcGxvdHNfbGVnJFVDUDIgKyBzY2FsZV9jb2xvcl9ncmFkaWVudChuYW1lPSdFeHByZXNzaW9uJywgbG93PSdncmF5JywgaGlnaD0nYmx1ZScsIGd1aWRlPSdjb2xvcmJhcicsIGxpbWl0cz1jKDAsNSkpICsgdGhlbWUocGxvdC50aXRsZT1lbGVtZW50X2JsYW5rKCksIGxlZ2VuZC50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0yMCksIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTIwKSwgbGVnZW5kLmtleS5oZWlnaHQgPSB1bml0KDEuMywgJ2NtJykpCgpkY25fZnAgPC0gZmVhdHVyZXBsb3RzX25vbGVnJERDTiArIHRoZW1lKHBsb3QudGl0bGU9ZWxlbWVudF9ibGFuaygpKQoKYXBvZF9mcCA8LSBmZWF0dXJlcGxvdHNfbGVnJEFQT0QgKyBzY2FsZV9jb2xvcl9ncmFkaWVudChuYW1lPSdFeHByZXNzaW9uJywgbG93PSdncmF5JywgaGlnaD0nYmx1ZScsIGd1aWRlPSdjb2xvcmJhcicpICsgdGhlbWUocGxvdC50aXRsZT1lbGVtZW50X2JsYW5rKCksIGxlZ2VuZC50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0yMCksIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTIwKSwgbGVnZW5kLmtleS5oZWlnaHQgPSB1bml0KDEuMywgJ2NtJykpCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTIsIGZpZy5hbGlnbiA9ICJjZW50ZXIifQptZXRhYm9saWNfZnAgPC0gcGxvdF9ncmlkKGFkaXBvcV9mcCwgdWNwMl9mcCwgbmNvbD0yLCByZWxfd2lkdGhzPWMoMC40MSwgMC41OSkpCmVjbV9mcCA8LSBwbG90X2dyaWQoZGNuX2ZwLCBhcG9kX2ZwLCBuY29sPTIsIHJlbF93aWR0aHM9YygwLjQxLCAwLjU5KSkKCnBsb3RfZ3JpZChtZXRhYm9saWNfZnAsIGVjbV9mcCwgbmNvbD0xKQpgYGAKCgpgYGB7cn0KCnNhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9GaWd1cmUzX2JlYW0vZmVhdHVyZXBsb3RzX21ldGFib2xpYy5wZGYiLCBtZXRhYm9saWNfZnAsIGJhc2Vfd2lkdGg9d2lkdGgsIGJhc2VfaGVpZ2h0PWhlaWdodCkKc2F2ZV9wbG90KCIuLi9maWd1cmVzL2ZpZ3VyZXNfcGFwZXIvbWFpbl9maWd1cmVzL0ZpZ3VyZTNfYmVhbS9mZWF0dXJlcGxvdHNfZWNtLnBkZiIsIGVjbV9mcCwgYmFzZV93aWR0aD13aWR0aCwgYmFzZV9oZWlnaHQ9aGVpZ2h0KQoKI3NhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9maWd1cmUzL2ZlYXR1cmVwbG90X0FESVBPUS5wZGYiLCBhZGlwb3FfZnAsIGJhc2Vfd2lkdGg9d2lkdGgsIGJhc2VfaGVpZ2h0PWhlaWdodCkKI3NhdmVfcGxvdCgiLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9maWd1cmUzL2ZlYXR1cmVwbG90X1VDUDIucGRmIiwgdWNwMl9mcCwgYmFzZV93aWR0aD13aWR0aCwgYmFzZV9oZWlnaHQ9aGVpZ2h0KQojc2F2ZV9wbG90KCIuLi9maWd1cmVzL2ZpZ3VyZXNfcGFwZXIvbWFpbl9maWd1cmVzL2ZpZ3VyZTMvZmVhdHVyZXBsb3RfRENOLnBkZiIsIGRjbl9mcCwgYmFzZV93aWR0aD13aWR0aCwgYmFzZV9oZWlnaHQ9aGVpZ2h0KQojc2F2ZV9wbG90KCIuLi9maWd1cmVzL2ZpZ3VyZXNfcGFwZXIvbWFpbl9maWd1cmVzL2ZpZ3VyZTMvZmVhdHVyZXBsb3RfQVBPRC5wZGYiLCBhcG9kX2ZwLCBiYXNlX3dpZHRoPXdpZHRoLCBiYXNlX2hlaWdodD1oZWlnaHQpCmBgYAoKIyNHTyBidWJibGUgcGxvdAoKYGBge3J9Cm5hbWUgPC0gJ2hlYXRtYXBfbG9nRkMwLjNfbmNsdXN0ZXI2Jwpmb2xkZXIgPC0gcGFzdGUoJy4uL3RhYmxlcy90YWJsZXNfcGFwZXIvYWxsX3RhYmxlcy9CRUFNLycsIG5hbWUsIHNlcD0nJykKI2NsdXN0ZXJzIDwtIGMoMSwyLDMsNCw2KQpjbHVzdGVycyA8LSBjKDIsNiwzKQpnc2VhIDwtIGxpc3QoKQpnZW5lbGlzdCA8LSBsaXN0KCkKCmZvciAoaSBpbiBjbHVzdGVycyl7CiAgZ3NlYV9jbHVzdGVyIDwtIHJlYWQudGFibGUocGFzdGUoZm9sZGVyLCAnL1JFVklHT19jbGVhbmVkLycsICdSRVZJR09fY2x1c3RlcicsIGksICdfY2xlYW5lZC50c3YnLCBzZXA9JycpLCBoZWFkZXI9VCkKICBnc2VhX2NsdXN0ZXJbJ2NsdXN0ZXInXSA8LSBpCiAgZ2VuZXNfY2x1c3RlciA8LSByZWFkLnRhYmxlKHBhc3RlKGZvbGRlciwgJy9nZW5lbGlzdF9jbHVzdGVyJywgaSwgJy50c3YnLCBzZXA9JycpLCBoZWFkZXI9VCkKICBnc2VhW1tpXV0gPC0gZ3NlYV9jbHVzdGVyCiAgZ2VuZWxpc3RbW2ldXSA8LSBnZW5lc19jbHVzdGVyCn0KCmdzZWEgPC0gZG8uY2FsbCgicmJpbmQiLCBnc2VhKQpnZW5lbGlzdCA8LSBkby5jYWxsKCJyYmluZCIsIGdlbmVsaXN0KQoKY3JlYXRlX3Rlcm1zIDwtIGZ1bmN0aW9uKGdzZWEpewogIHJldHVybihkYXRhLmZyYW1lKGNhdGVnb3J5PWdzZWEkZ3NlYS5kb21haW4sIElEPWdzZWEkcmV2aWdvLnRlcm1fSUQsIHRlcm09Z3NlYSRyZXZpZ28uZGVzY3JpcHRpb24sIGFkal9wdmFsPWdzZWEkZ3NlYS5wLnZhbHVlLCBnZW5lcz1nc2VhJGdzZWEuaW50ZXJzZWN0aW9uLCBjbHVzdGVyPWdzZWEkY2x1c3RlcikpCn0KCmNyZWF0ZV9nZW5lcyA8LSBmdW5jdGlvbihnZW5lbGlzdCl7CiAgcmV0dXJuKGRhdGEuZnJhbWUoSUQ9Z2VuZWxpc3QkZ2VuZV9zaG9ydF9uYW1lLCBsb2dGQz1nZW5lbGlzdCRhdmdMb2dGQ19TdGF0ZTJfU3RhdGUzKSkKfQoKdGVybXMgPC0gY3JlYXRlX3Rlcm1zKGdzZWEpCmdlbmVzIDwtIGNyZWF0ZV9nZW5lcyhnZW5lbGlzdCkKY2lyYyA8LSBjaXJjbGVfZGF0KHRlcm1zLCBnZW5lcykKYGBgCgpgYGB7ciwgZmlnLmhlaWdodCA9IDcsIGZpZy53aWR0aCA9IDIwLCBmaWcuYWxpZ24gPSAiY2VudGVyIn0KR09CdWJibGVfbW9kaWZpZWQgPC0gZnVuY3Rpb24oZGF0YSwgZGlzcGxheSwgdGl0bGUsIGNvbG91ciwgbGFiZWxzLCBJRCA9IFQsIHRhYmxlLmxlZ2VuZCA9IFQsIHRhYmxlLmNvbCA9IFQsIGJnLmNvbCA9IEYsIHpzY29yZV90aHJlc2hvbGQ9MCwgZ2dyZXBlbF9saW5lY29sPSdibGFjaycsIHRleHRfc2l6ZV9heGVzPTIwLCB0ZXh0X3NpemVfYXhlc19sYWJlbD0yMCwgdGV4dF9zaXplPTEwLCB0ZXh0X3NpemVfbGVnZW5kPTcsIHRleHRfc2l6ZV90aHJlc2hvbGQ9MTAsIGxlZ2VuZF9wb2ludF9zaXplPTIwKXsKICB6c2NvcmUgPC0gYWRqX3B2YWwgPC0gY2F0ZWdvcnkgPC0gY291bnQgPC0gaWQgPC0gdGVybSA8LSBOVUxMCiAgaWYgKG1pc3NpbmcoZGlzcGxheSkpIGRpc3BsYXkgPC0gJ3NpbmdsZScKICBpZiAobWlzc2luZyh0aXRsZSkpIHRpdGxlIDwtICcnCiAgaWYgKG1pc3NpbmcoY29sb3VyKSkgY29scyA8LSBjKCJjaGFydHJldXNlNCIsICJicm93bjIiLCAiY29ybmZsb3dlcmJsdWUiKSBlbHNlIGNvbHMgPC0gY29sb3VyCiAgaWYgKG1pc3NpbmcobGFiZWxzKSkgbGFiZWxzIDwtIDUKICBpZiAoYmcuY29sID09IFQgJiBkaXNwbGF5ID09ICdzaW5nbGUnKSBjYXQoIlBhcmFtZXRlciBiZy5jb2wgd2lsbCBiZSBpZ25vcmVkLiBUbyB1c2UgdGhlIHBhcmFtZXRlciBjaGFuZ2UgZGlzcGxheSB0byAnbXVsdGlwbGUnIikKICAKICBjb2xuYW1lcyhkYXRhKSA8LSB0b2xvd2VyKGNvbG5hbWVzKGRhdGEpKQogIHRtcF9sYWIgPC0gZGF0YS5mcmFtZShjYXRzID0gYygnQmlvbG9naWNhbCBQcm9jZXNzJywgJ0NlbGx1bGFyIENvbXBvbmVudCcsICdNb2xlY3VsYXIgRnVuY3Rpb24nKSwgCiAgICAgICAgICAgICAgICAgICAgICAgIGNhdC5hYmIgPSBjKCdCUCcsICdDQycsICdNRicpLAogICAgICAgICAgICAgICAgICAgICAgICBsb2N5ID0gYyhtYXRjaCgnQlAnLCBkYXRhJGNhdGVnb3J5KSwgbWF0Y2goJ0NDJywgZGF0YSRjYXRlZ29yeSksIG1hdGNoKCdNRicsIGRhdGEkY2F0ZWdvcnkpKSwKICAgICAgICAgICAgICAgICAgICAgICAgY29scyA9IGNvbHMsCiAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGKQogIHRtcF9sYWIgPC0gdG1wX2xhYltvcmRlcih0bXBfbGFiJGxvY3kpLF0KICBpZighJ2NvdW50JyVpbiVjb2xuYW1lcyhkYXRhKSl7CiAgICByYW5nIDwtIGMoNSwgNSkKICAgIGRhdGEkY291bnQgPC0gcmVwKDEsIGRpbShkYXRhKVsxXSkKICB9ZWxzZSB7cmFuZyA8LSBjKDEsIDMwKX0KICBkYXRhJGFkal9wdmFsIDwtIC1sb2coZGF0YSRhZGpfcHZhbCwgMTApCiAgc3ViIDwtIGRhdGFbIWR1cGxpY2F0ZWQoZGF0YSR0ZXJtKSwgXQogIGcgPC0gZ2dwbG90KHN1YiwgYWVzKHpzY29yZSwgYWRqX3B2YWwsIGZpbGwgPSBjYXRlZ29yeSwgc2l6ZSA9IGNvdW50KSkrCiAgICBsYWJzKHRpdGxlID0gdGl0bGUsIHggPSAnei1zY29yZScsIHkgPSAnLWxvZyAoYWRqIHAtdmFsdWUpJykrCiAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIGNvbCA9ICdibGFjaycsIGFscGhhID0gMSAvIDIpKyAjYWRkIGFsbCBidWJibGVzCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxLjMsIGNvbCA9ICdvcmFuZ2UnKSsgI2FkZCB0aHJlc2hvbGQgZm9yIHAtdmFsdWU9MC4wNQogICAgc2NhbGVfc2l6ZShyYW5nZSA9IHJhbmcsIGd1aWRlID0gJ25vbmUnKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoMCw0NSkpCiAgCiAgc3ViMiA8LSBzdWJzZXQoc3ViLCBzdWJzZXQ9c3ViJGFkal9wdmFsID49IGxhYmVscykKICBzdWIyIDwtIHN1YnNldChzdWIyLCBzdWJzZXQ9YWJzKHN1YjIkenNjb3JlKSA+PSB6c2NvcmVfdGhyZXNob2xkKQoKICAgIGcgPC0gZyArIHNjYWxlX2ZpbGxfbWFudWFsKCcnLCB2YWx1ZXMgPSB0bXBfbGFiJGNvbHMsIGxhYmVscyA9IHRtcF9sYWIkY2F0cykrCiAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdyaWdodCcsIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMSwgJ2NtJyksIGxlZ2VuZC50aXRsZT1lbGVtZW50X3RleHQoZmFjZT0nYm9sZCcpKSArCiAgICAgIGd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZT1sZWdlbmRfcG9pbnRfc2l6ZSkpKQogICAgICBhbm5vdGF0ZSAoInRleHQiLCB4ID0gMC42LCB5ID0gMi4yLCBsYWJlbCA9ICJUaHJlc2hvbGQiLCBjb2xvdXIgPSAib3JhbmdlIiwgc2l6ZSA9IHRleHRfc2l6ZV90aHJlc2hvbGQpCiAgICBnIDwtIGcgKyBnZW9tX3RleHRfcmVwZWwoZGF0YSA9IHN1YjIsIGFlcyh4ID0genNjb3JlLCB5ID0gYWRqX3B2YWwsIGxhYmVsID0gdGVybSksIHNpemUgPSB0ZXh0X3NpemUsIHNlZ21lbnQuY29sb3IgPSBnZ3JlcGVsX2xpbmVjb2wpCiAgICBnIDwtICBnICsgCiAgICAgICAgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSB0ZXh0X3NpemVfYXhlcyksIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAnZ3JleTgwJyksIGF4aXMudGlja3MgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gJ2dyZXk4MCcpLCBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSB0ZXh0X3NpemVfYXhlc19sYWJlbCwgZmFjZSA9ICdib2xkJyksIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9dGV4dF9zaXplX2xlZ2VuZCksIGxlZ2VuZC50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT10ZXh0X3NpemVfbGVnZW5kKSkKIHJldHVybihnKQp9CgpwIDwtIEdPQnViYmxlX21vZGlmaWVkKGNpcmMsIGxhYmVscz0yLCBJRD1GLCB0YWJsZS5sZWdlbmQgPSBGLCB6c2NvcmVfdGhyZXNob2xkPTQuNSwgZ2dyZXBlbF9saW5lY29sPSd0cmFuc3BhcmVudCcsIHRleHRfc2l6ZV9heGVzPTE1LCB0ZXh0X3NpemVfYXhlc19sYWJlbD0xNSwgdGV4dF9zaXplPTQuNSwgdGV4dF9zaXplX2xlZ2VuZD0xNSwgdGV4dF9zaXplX3RocmVzaG9sZD01LCBsZWdlbmRfcG9pbnRfc2l6ZT0xNSkKcApgYGAKCmBgYHtyfQpzYXZlX3Bsb3QoJy4uL2ZpZ3VyZXMvZmlndXJlc19wYXBlci9tYWluX2ZpZ3VyZXMvRmlndXJlM19iZWFtLzE4MDgzMV9iZWFtR09fY2x1c3Rlci0yLTYtMy5wZF9sYWJlbHMzX3pzY29yZTQuNS5wZGYnLCBwLCBiYXNlX3dpZHRoPTIwLCBiYXNlX2hlaWdodD03KQojc2F2ZV9wbG90KCcuLi9maWd1cmVzL2ZpZ3VyZXNfcGFwZXIvbWFpbl9maWd1cmVzL0ZpZ3VyZTNfYmVhbS8xODA4MzFfYmVhbUdPX2FsbC10ZXJtcy5wZF9sYWJlbHMzX3pzY29yZTQuNS5wZGYnLCBwLCBiYXNlX3dpZHRoPTIwLCBiYXNlX2hlaWdodD03KQpgYGAKCiNQZXJjZW50Lm1pdG8KCmBgYHtyIGVjaG89VCwgcmVzdWx0cz0naGlkZSd9CnBlcmNlbnRfbWl0b19mcCA8LSBGZWF0dXJlUGxvdChzZXVyb2JqLCBmZWF0dXJlcy5wbG90PWMoJ3BlcmNlbnQubWl0by4xMDAnKSwgY29scy51c2U9YygnZ3JheScsICdibHVlJyksIG5vLmxlZ2VuZD1GLCBkby5yZXR1cm49VCwgbm8uYXhlcz1ULCBtYXguY3V0b2ZmID0gYygxMCkpJHBlcmNlbnQubWl0byArIGdndGl0bGUoJycpICsgc2NhbGVfY29sb3JfZ3JhZGllbnQobmFtZT0nJSBtaXRvY2hvbmRyaWFsXG5nZW5lIGV4cHJlc3Npb24nLCBsb3c9J2dyYXknLCBoaWdoPSdibHVlJywgZ3VpZGU9J2NvbG9yYmFyJykgKyB0aGVtZShsZWdlbmQua2V5LmhlaWdodCA9IHVuaXQoMS42LCAnY20nKSkKYGBgCgpgYGB7ciwgZmlnLmhlaWdodCA9IDQsIGZpZy53aWR0aCA9IDUuNSwgZmlnLmFsaWduID0gImNlbnRlciJ9CnBlcmNlbnRfbWl0b19mcApgYGAKCmBgYHtyfQpzYXZlX3Bsb3QoIi4uL2ZpZ3VyZXMvZmlndXJlc19wYXBlci9tYWluX2ZpZ3VyZXMvRmlndXJlM19iZWFtL2ZlYXR1cmVwbG90X1BFUkNFTlRfTUlUTy5wZGYiLCBwZXJjZW50X21pdG9fZnAsIGJhc2Vfd2lkdGg9d2lkdGgsIGJhc2VfaGVpZ2h0PWhlaWdodCkKYGBgCgojQkFUTEFTCgpgYGB7cn0KYmF0bGFzX3Jlc3VsdHMgPC0gcmVhZC50YWJsZSgnLi4vdGFibGVzL3RhYmxlc19wYXBlci9zdXBwbGVtZW50YXJ5X3RhYmxlcy9CQVRMQVMvQkFUTEFTX2JyYW5jaF9oaWdoX3Jlcy50eHQnLCBzZXA9J1x0JywgaGVhZGVyPVQpCmJhdGxhc19yZXN1bHRzWydwc2V1ZG90aW1lX2RlY2lsZSddIDwtIHNldXJvYmpAbWV0YS5kYXRhJHBzZXVkb3RpbWVfZGVjaWxlW21hdGNoKGJhdGxhc19yZXN1bHRzJHNhbXBsZSwgc2V1cm9iakBtZXRhLmRhdGEkYnJhbmNoX2hpZ2hfcmVzKV0KYmF0bGFzX3Jlc3VsdHNbJ2JyYW5jaCddIDwtIHNldXJvYmpAbWV0YS5kYXRhJGJyYW5jaFttYXRjaChiYXRsYXNfcmVzdWx0cyRzYW1wbGUsIHNldXJvYmpAbWV0YS5kYXRhJGJyYW5jaF9oaWdoX3JlcyldCmJhdGxhc19yZXN1bHRzIDwtIGJhdGxhc19yZXN1bHRzICU+JSBtdXRhdGUoYmxvY2tfYnJhbmNoID0gaWZfZWxzZShicmFuY2ggPT0gJ1Byb2dlbml0b3InLCAnQmVnaW5uaW5nJywgJ0VuZCcpKQpiYXRsYXNfcmVzdWx0c1snYnJvd25fY2VudGVyZWQnXSA8LSBiYXRsYXNfcmVzdWx0cyRicm93biAtIDAuNQpiYXRsYXNfcmVzdWx0c1sncmF0aW8nXSA8LSBiYXRsYXNfcmVzdWx0cyRicm93bi9iYXRsYXNfcmVzdWx0cyR3aGl0ZQpgYGAKCmBgYHtyLCBmaWcuaGVpZ2h0ID0gNiwgZmlnLndpZHRoID0gOCwgZmlnLmFsaWduID0gImNlbnRlciJ9CnAgPC0gZ2dwbG90KGJhdGxhc19yZXN1bHRzLCBhZXMoeD1hcy5mYWN0b3IocHNldWRvdGltZV9kZWNpbGUpLCB5PWJyb3duX2NlbnRlcmVkLCBmaWxsPWJyYW5jaCkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlMih3aWR0aD0wLjksIHByZXNlcnZlPSdzaW5nbGUnKSkgKwogIGxhYnMoeD0iUHNldWRvdGltZSAoc3RyZXRjaGVkKSIsIGZpbGw9IkJyYW5jaCIsIHk9TlVMTCkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jb2xvcm1hcC5icmFuY2hlcywgbGFiZWxzPWMoJ0wnLCAnVScsICdQJykpICsKICBmYWNldF9ncmlkKGNvbHM9dmFycyhibG9ja19icmFuY2gpLCBzd2l0Y2g9J3gnKSArIAogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHM9YygtMC41LCAwLjUpLCBicmVha3M9c2VxKC0wLjUsIDAuNSwgYnk9MC41KSwgbGFiZWxzPWMoJzEwMCUgd2hpdGUnLCAnNTAvNTAnLCAnMTAwJSBicm93bicpKSArCiAgdGhlbWUoc3RyaXAuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCksIHN0cmlwLnBsYWNlbWVudD0nb3V0c2lkZScsIHN0cmlwLnRleHQgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKHQgPSAyMCwgciA9IDAsIGIgPSAwLCBsID0gMCkpKQpwCmBgYAoKYGBge3J9CnNhdmVfcGxvdCgnLi4vZmlndXJlcy9maWd1cmVzX3BhcGVyL21haW5fZmlndXJlcy9GaWd1cmUzX2JlYW0vQkFUTEFTX3Jlc3VsdHMucGRmJywgcCwgYmFzZV9oZWlnaHQ9NSwgYmFzZV93aWR0aD04KQpgYGAKCgojI1NPTSBGaWd1cmVzCgpDbHVzdGVycwoKVEYgYW5hbHlzaXMKCmBgYHtyLCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDEyLCBmaWcuYWxpZ24gPSAiY2VudGVyIn0KZmlnIDwtIHBsb3RfZ3JpZCgKICBUU05FUGxvdChzZXVyb2JqLCBncm91cC5ieT0ncmVzLjAuNScsIHB0LnNpemU9cHQuc2l6ZS50c25lLCBkby5sYWJlbD1UKSwKICBUU05FUGxvdChzZXVyb2JqLCBncm91cC5ieT0ncmVzLjAuNycsIHB0LnNpemU9cHQuc2l6ZS50c25lLCBkby5sYWJlbD1UKSwKICBUU05FUGxvdChzZXVyb2JqLCBncm91cC5ieT0ncmVzLjEnLCBwdC5zaXplPXB0LnNpemUudHNuZSwgZG8ubGFiZWw9VCksCiAgVFNORVBsb3Qoc2V1cm9iaiwgZ3JvdXAuYnk9J3Jlcy4xLjUnLCBwdC5zaXplPXB0LnNpemUudHNuZSwgZG8ubGFiZWw9VCksCiAgbmNvbD0yLCBsYWJlbHM9J2F1dG8nCikKYGBgCgoKTWV0YWJvbGljIGFuZCBFQ00gZ2VuZXMKCmBgYHtyfQoKYGBgCgoKYGBge3J9CkZlYXR1cmVQbG90KHNldXJvYmosIGZlYXR1cmVzLnBsb3Q9J1BzZXVkb3RpbWUnKQpgYGAKCg==